package com.ddh.codeduck.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.codeduck.pojo.dto.CodeDuckQuestionDTO;
import com.codeduck.pojo.entity.CodeDuckQuestion;
import com.codeduck.pojo.entity.CodeDuckQuestionTag;
import com.codeduck.pojo.entity.CodeDuckTag;
import com.codeduck.pojo.entity.SysDictData;
import com.ddhcodeduck.common.enums.QuestionDifficulty;
import com.ddh.codeduck.mapper.CodeDuckQuestionMapper;
import com.codeduck.pojo.req.CodeDuckQuestionPageReq;
import com.ddh.codeduck.service.*;
import com.codeduck.pojo.vo.CodeDuckQuestionVO;
import com.ddhcodeduck.common.exception.BusinessException;
import com.ddhcodeduck.common.exception.ErrorCode;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

import static com.ddhcodeduck.common.constant.DictDataConstant.DICT_TYPE_QUESTION_CATEGORY;

/**
 * <p>
 * 题目表 服务实现类
 * </p>
 *
 * @author ddh
 * @since 2020-05-05
 */
@Service
public class CodeDuckQuestionServiceImpl extends ServiceImpl<CodeDuckQuestionMapper, CodeDuckQuestion> implements ICodeDuckQuestionService {

    @Resource
    private ISysDictDataService sysDictDataService;

    @Resource
    private ICodeDuckQuestionTagService codeDuckQuestionTagService;

    @Resource
    private ICodeDuckTagService codeDuckTagService;

    @Override
    public IPage<CodeDuckQuestionVO> listByQuestionCategory(CodeDuckQuestionPageReq codeDuckQuestionPageReq) {
        String questionCategoryId = codeDuckQuestionPageReq.getQuestionCategoryId();
        Integer current = codeDuckQuestionPageReq.getCurrent();
        Integer pageSize = codeDuckQuestionPageReq.getPageSize();
        String title = codeDuckQuestionPageReq.getTitle();
        Integer difficulty = codeDuckQuestionPageReq.getDifficulty();

        LambdaQueryWrapper<CodeDuckQuestion> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper
                .eq(StringUtils.isNotEmpty(questionCategoryId), CodeDuckQuestion::getQuestionCategoryId, questionCategoryId)
                .like(StringUtils.isNotEmpty(title), CodeDuckQuestion::getTitle, title)
                .eq(difficulty != null, CodeDuckQuestion::getDifficulty, difficulty);

        // 根据 sortOrder的值设置排序条件
        String sortOrder = codeDuckQuestionPageReq.getSortOrder();
        if (sortOrder != null && !sortOrder.isEmpty()) {
            if ("desc".equalsIgnoreCase(sortOrder)) {
                queryWrapper.orderByDesc(CodeDuckQuestion::getDifficulty);
            } else {
                queryWrapper.orderByAsc(CodeDuckQuestion::getDifficulty);
            }
        }

        IPage<CodeDuckQuestion> questionPage;

        // 判断是否传了分页参数
        if (current == null || pageSize == null) {
            // 不分页查询全部数据
            List<CodeDuckQuestion> questionList = list(queryWrapper);
            // 构造一个伪分页对象，模拟不分页的结果
            Page<CodeDuckQuestion> fakePage = new Page<>();
            fakePage.setRecords(questionList);
            fakePage.setSize(questionList.size());
            fakePage.setTotal(questionList.size());
            questionPage = fakePage;
        } else {
            // 分页查询
            Page<CodeDuckQuestion> page = new Page<>(current, pageSize);
            questionPage = page(page, queryWrapper);
        }

        // 将 CodeDuckQuestion 转换为 CodeDuckQuestionVO
        return questionPage.convert(question -> {
            CodeDuckQuestionVO vo = new CodeDuckQuestionVO();
            BeanUtils.copyProperties(question, vo);
            List<CodeDuckTag> codeDuckTags = codeDuckQuestionTagService.listTagsByQuestionId(question.getId());
            if (CollectionUtils.isNotEmpty(codeDuckTags)) {
                List<String> tagNameList = codeDuckTags.stream()
                        .map(CodeDuckTag::getName)
                        .collect(Collectors.toList());
                List<String> tagIdList = codeDuckTags.stream()
                        .map(CodeDuckTag::getId)
                        .collect(Collectors.toList());
                vo.setTagIdList(tagIdList);
                vo.setTagNameList(tagNameList);
            }
            vo.setDifficultyName(QuestionDifficulty.fromCode(question.getDifficulty()).getName());
            return vo;
        });
    }


    /**
     * 新增或者修改题目
     */
    @Transactional
    @Override
    public Boolean mySaveOrUpdateQuestion(CodeDuckQuestionDTO codeDuckQuestionDTO) {
        // 1. 验证题目难度
        List<SysDictData> questionDifficultyList = sysDictDataService.list(new LambdaQueryWrapper<SysDictData>()
                .eq(SysDictData::getDictType, DICT_TYPE_QUESTION_CATEGORY)
        );
        if (CollectionUtils.isEmpty(questionDifficultyList)) {
            throw new BusinessException(ErrorCode.QUESTION_TYPE_EMPTY_ERROR);
        }
        Integer difficulty = codeDuckQuestionDTO.getDifficulty();
        if (difficulty == null) {
            throw new BusinessException(ErrorCode.QUESTION_DIFFICULTY_EMPTY_ERROR);
        }
        if (questionDifficultyList.stream().noneMatch(dict -> dict.getItemValue().equals(difficulty.toString()))) {
            throw new BusinessException(ErrorCode.QUESTION_DIFFICULTY_NOT_FOUND_ERROR);
        }

        // 2. 保存或更新题目
        CodeDuckQuestion codeDuckQuestion = new CodeDuckQuestion();
        BeanUtils.copyProperties(codeDuckQuestionDTO, codeDuckQuestion);
        boolean result = saveOrUpdate(codeDuckQuestion);

        if (!result) {
            return false;
        }

        //验证题目标签不能为空
        List<String> tagIdList = codeDuckQuestionDTO.getTagIdList();
        if (CollectionUtils.isEmpty(tagIdList)) {
            throw new BusinessException(ErrorCode.QUESTION_TAG_EMPTY_ERROR);
        }
        //题目标签必须是二级标签，也就是parentId不能为空
        for (String tagId : tagIdList) {
            CodeDuckTag codeDuckTag = codeDuckTagService.getById(tagId);
            if (codeDuckTag == null) {
                throw new BusinessException(ErrorCode.QUESTION_TAG_NOT_SECOND_LEVEL_ERROR);
            }
        }

        // 3. 处理题目标签关联
        if (CollectionUtils.isNotEmpty(tagIdList)) {
            if (codeDuckQuestionDTO.getId() == null) {
                // 新增操作 - 直接插入标签关联
                List<CodeDuckQuestionTag> relations = tagIdList.stream()
                        .map(tagId -> {
                            CodeDuckQuestionTag relation = new CodeDuckQuestionTag();
                            relation.setQuestionId(codeDuckQuestion.getId());
                            relation.setTagId(tagId);
                            return relation;
                        })
                        .collect(Collectors.toList());
                codeDuckQuestionTagService.saveBatch(relations);
            } else {
                // 修改操作 - 智能更新关联关系
                updateQuestionTags(codeDuckQuestion.getId(), tagIdList);
            }
        } else if (codeDuckQuestionDTO.getId() != null) {
            // 修改操作但未传标签ID - 删除所有关联
            codeDuckQuestionTagService.remove(
                    new LambdaQueryWrapper<CodeDuckQuestionTag>()
                            .eq(CodeDuckQuestionTag::getQuestionId, codeDuckQuestion.getId())
            );
        }

        return true;
    }

    /**
     * 智能更新题目标签关联（保留已有的关联ID）
     */
    private void updateQuestionTags(String questionId, List<String> newTagIds) {
        // 1. 查询现有关联
        List<CodeDuckQuestionTag> existingRelations = codeDuckQuestionTagService.list(
                new LambdaQueryWrapper<CodeDuckQuestionTag>()
                        .eq(CodeDuckQuestionTag::getQuestionId, questionId)
        );

        // 3. 找出需要保留、需要删除和需要新增的关联
        List<CodeDuckQuestionTag> toKeep = existingRelations.stream()
                .filter(relation -> newTagIds.contains(relation.getTagId()))
                .collect(Collectors.toList());

        List<String> toDeleteIds = existingRelations.stream()
                .filter(relation -> !newTagIds.contains(relation.getTagId()))
                .map(CodeDuckQuestionTag::getId)
                .collect(Collectors.toList());

        List<String> existingTagIds = toKeep.stream()
                .map(CodeDuckQuestionTag::getTagId)
                .collect(Collectors.toList());

        List<CodeDuckQuestionTag> toAdd = newTagIds.stream()
                .filter(tagId -> !existingTagIds.contains(tagId))
                .map(tagId -> {
                    CodeDuckQuestionTag relation = new CodeDuckQuestionTag();
                    relation.setQuestionId(questionId);
                    relation.setTagId(tagId);
                    return relation;
                })
                .collect(Collectors.toList());

        // 4. 执行操作
        if (!toDeleteIds.isEmpty()) {
            codeDuckQuestionTagService.removeByIds(toDeleteIds);
        }
        if (!toAdd.isEmpty()) {
            codeDuckQuestionTagService.saveBatch(toAdd);
        }
        // 保留的关联关系自动保持原样
    }
}

